package mylab.thread;


class WaitNotifyExample { 
	
static class Q { 
	int n=0;
	boolean valueSet=false;

	synchronized int get() throws InterruptedException {
		
		if(!valueSet)
		{
			wait();
		}
		
		System.out.println("Got: " + n);
		
		valueSet=false;
		notify();
		return n;
		
	}
	
	synchronized void put(int n) throws InterruptedException {
		
		if(valueSet)
		{
			wait();
		}
		 
		System.out.println("Put: " + n);
		this.n=n;
		valueSet=true;
		notify();
	} 
	
}

static class Producer implements Runnable { 
	Q q; 
	Producer(Q q) { 
		this.q = q; 
		new Thread(this, "Producer").start(); 
	} 

	public void run() { 
		int i = 0; 
		while(true) { 
			try {
				q.put(i++);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} 
		} 
	} 	
}

static class Consumer implements Runnable { 
	Q q; 
	
	Consumer(Q q) { 
		this.q = q; 
		new Thread(this, "Consumer").start(); 
	} 
	
	public void run() { 
		while(true) { 
			try {
				q.get();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} 
		} 
	} 
}


public static void main(String args[]) { 
	Q q = new Q(); 
	new Producer(q); 
	new Consumer(q); 
	System.out.println("Press Control-C to stop."); 
	} 
}